#include "Logger.h"
#include "TcpServer.h"
#include "TcpClient.h"
#include "spdlog/common.h"
#include <functional>
#include <memory>
#include <string>

class EchoSession {
public:
    using Ptr = std::shared_ptr<EchoSession>;
    EchoSession() = default;
    ~EchoSession() = default;

    std::string m_Data;

    void HandleRead(std::shared_ptr<GiSo::TcpConnection> conn, GiSo::Buffer& buffer) {
        buffer.AssignToString(m_Data);
        GS_INFO("Server {0} Received data: {1}", conn->GetFd(), m_Data);
        
        // test
        // 返回简单的 HTTP 响应
        std::string response = "HTTP/1.1 200 OK\r\nContent-Length: " + 
                            std::to_string(m_Data.size()) + 
                            "\r\n\r\n" + m_Data;
        conn->Send(response);
        m_Data.clear();
        buffer.Clear();
    }

    void HandleWriteComplete(std::shared_ptr<GiSo::TcpConnection> conn) {
        GS_INFO("Server {0} TcpConnection::HandleWriteComplete", conn->GetFd());
    }

    void HandleClose(std::shared_ptr<GiSo::TcpConnection> conn) {
        GS_INFO("Server {0} TcpConnection::HandleClose", conn->GetFd());
    }

    static bool AddSession(GiSo::TcpConnection::Ptr conn, const GiSo::InetAddress& clientAddr) {
        GS_INFO("Server New connection from {0}:{1}", clientAddr.GetIp(), clientAddr.GetPort());
        EchoSession::Ptr session = std::make_shared<EchoSession>();
        conn->SetReadCallback(std::bind(&EchoSession::HandleRead, session, std::placeholders::_1, std::placeholders::_2));
        conn->SetCloseCallback(std::bind(&EchoSession::HandleClose, session, std::placeholders::_1));
        // conn->SetWriteCompleteCallback(std::bind(&EchoSession::HandleWriteComplete, session, std::placeholders::_1));
        return true;
    }
};

void RunClient(){
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    GiSo::TcpClient client;
    if(client.ConnectToServer("127.0.0.1", 1127)){
        for(int i = 0; i < 5; i++){
            if(client.SendData("Hello from client! - "+std::to_string(i))>0){
                GS_INFO("Client sent data {0}", i);
            }
            else {
                GS_ERROR("Client send error");
            }
            if(client.Wait(2000)){
                GS_INFO("Client received data {0}", client.ReceiveData());
            }
            else {
                GS_ERROR("Client receive error {0}", i);
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
    }
}

int main() {

    GiSo::Logger::Options options;
    options.outputType = GiSo::Logger::OutputType::Both;
    options.filename = "echo_server.log";
    options.level = spdlog::level::warn;
    GiSo::Logger::init(options);

    GiSo::InetAddress addr(1127); // Different port for echo server
    GiSo::TcpServer server(addr, 3);

    server.SetNewConnectionCallback(EchoSession::AddSession);

    GS_INFO("Echo server listening on port 1127");

    // std::thread clientThread(RunClient);

    server.Start();

    return 0;
}